package com.gl.portal.system.service;

import com.gl.common.constant.Constants;
import com.gl.common.enums.DelFlagEnum;
import com.gl.common.enums.StatusEnum;
import com.gl.common.exception.CustomException;
import com.gl.common.util.SecurityUtils;
import com.gl.common.util.StringUtils;
import com.gl.common.util.sql.SqlUtils;
import com.gl.framework.security.LoginUser;
import com.gl.framework.web.domain.PageData;
import com.gl.portal.system.entity.SysDept;
import com.gl.portal.system.entity.SysRole;
import com.gl.portal.system.entity.SysUser;
import com.gl.portal.system.entity.SysUserRole;
import com.gl.portal.system.repository.SysDeptRepository;
import com.gl.portal.system.repository.SysRoleRepository;
import com.gl.portal.system.repository.SysUserRepository;
import com.gl.portal.system.repository.SysUserRoleRepository;
import com.gl.portal.system.vo.SysDeptVo;
import com.gl.portal.system.vo.SysRoleVo;
import com.gl.portal.system.vo.SysUserVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cglib.beans.BeanCopier;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 用户服务实现类
 */
@Service
public class SysUserService {

    @Autowired
    private JdbcTemplate jdbcTemplate;

    @Autowired
    private SysUserRepository userRepository;

    @Autowired
    private SysDeptRepository deptRepository;

    @Autowired
    private SysRoleRepository roleRepository;

    @Autowired
    private SysUserRoleRepository userRoleRepository;
    @Autowired
    private SysRoleService roleService;

    /**
     * 统计数量
     */
    private static final String SQL_COUNT = "SELECT COUNT(1) AS count \n";
    /**
     * 列表
     */
    private static final String SELECT_COLUMNS = "SELECT \n" +
            "u.id, u.dept_id, u.login_name, u.user_name, u.email, u.avatar, u.phone, u.password, u.gender, u.status, u.is_deleted, u.create_user_id, u.create_time, \n" +
            "d.dept_name \n";
    /**
     * 表
     */
    private static final String SELECT_FROM = "FROM sys_user u LEFT JOIN sys_dept d ON u.dept_id = d.id \n";
    /**
     * 排序
     */
//	private static final String SELECT_ORDER = "ORDER BY u.create_time DESC \n";
    /**
     * 分页
     */
    private static final String SQL_PAGE = "LIMIT ? OFFSET ?";

    /**
     * 根据条件分页查询用户列表
     *
     * @param filter 条件过滤
     * @return 用户信息集合信息
     */
    public PageData<SysUserVo> selectUserList(SysUserVo filter) {
        PageData<SysUserVo> pageData = new PageData<>();

        // 数据权限
        LoginUser loginUser = SecurityUtils.getLoginUser();
        List<Long> dataScopes = loginUser.getDataScopes();
        SysUserVo user = loginUser.getUser();
        boolean admin = SecurityUtils.isAdmin(user.getId());
        if (!admin && StringUtils.isEmpty(dataScopes)) {
            return pageData;
        }

        StringBuilder where = new StringBuilder("WHERE u.is_deleted = ? \n");
        List<Object> args = new ArrayList<>();

        args.add(DelFlagEnum.OK.value());

        if (!admin) {
            where.append("AND u.dept_id IN ");
            where.append(SqlUtils.foreachIn(dataScopes.size()));
            args.addAll(dataScopes);
        }

        if (filter != null) {
            if (StringUtils.isNotBlank(filter.getLoginName())) {
                where.append("AND u.login_name LIKE concat('%', ?, '%') \n");
                args.add(filter.getLoginName());
            }
            if (StringUtils.isNotBlank(filter.getPhone())) {
                where.append("AND u.phone LIKE concat('%', ?, '%') \n");
                args.add(filter.getPhone());
            }
            if (filter.getStatus() != null) {
                where.append("AND u.status = ? \n");
                args.add(filter.getStatus());
            }
            if (StringUtils.isNotBlank(filter.getBeginTime())) {
                where.append("AND DATE_FORMAT(u.create_time,'%Y-%m-%d') >= ? \n");
                args.add(filter.getBeginTime());
            }
            if (StringUtils.isNotBlank(filter.getEndTime())) {
                where.append("AND DATE_FORMAT(u.create_time,'%Y-%m-%d') <= ? \n");
                args.add(filter.getEndTime());
            }
            if (filter.getDeptId() != null) {
                where.append("AND (u.dept_id = ? OR u.dept_id IN ( SELECT t.id FROM sys_dept t WHERE FIND_IN_SET (?,ancestors) )) \n");
                args.add(filter.getDeptId());
                args.add(filter.getDeptId());
            }
        }

        // 总记录数
        Long total = jdbcTemplate.queryForObject(SQL_COUNT + SELECT_FROM + where, Long.class, args.toArray());

        // 分页数据
        args.add(filter.getPageSize());
        args.add((filter.getPageNumber() - 1) * filter.getPageSize());
        List<SysUserVo> data = jdbcTemplate.query(SELECT_COLUMNS + SELECT_FROM + where + SQL_PAGE, BeanPropertyRowMapper.newInstance(SysUserVo.class), args.toArray());

        if (data.isEmpty()) {
            return pageData;
        }

        // 查询部门信息
        List<Long> deptIds = data.stream().filter(vo -> vo.getDeptId() != null).map(SysUserVo::getDeptId).distinct().collect(Collectors.toList());
        if (!deptIds.isEmpty()) {
            Map<Long, SysDeptVo> map = deptRepository.findByIdIn(deptIds).stream().collect(Collectors.toMap(SysDept::getId, dept -> this.deptConvert(dept)));
            if (!CollectionUtils.isEmpty(map)) {
                data.forEach(vo -> vo.setDept(map.get(vo.getDeptId())));
            }
        }
        //查询角色
        List<SysUserRole>  sysUserRoleList=userRoleRepository.findAll();
        List<SysRoleVo> roles = roleService.selectRoleAll();
        for(SysUserVo vo : data){
            for(SysUserRole sysUserRole : sysUserRoleList){
                if(vo.getId().equals(sysUserRole.getUserId())){
                    vo.getRoleIds().add(sysUserRole.getRoleId());
                    for(SysRoleVo sysRoleVo : roles){
                        if(sysUserRole.getRoleId().equals(sysRoleVo.getId())){
                            vo.getRoles().add(sysRoleVo);
                        }
                    }

                }
            }
        }

        pageData.setTotal(total);
        pageData.setData(data);

        return pageData;
    }

    /**
     * 部门数据转换
     *
     * @param entity
     * @return
     */
    private SysDeptVo deptConvert(SysDept entity) {
        BeanCopier beanCopier = BeanCopier.create(SysDept.class, SysDeptVo.class, false);
        SysDeptVo vo = new SysDeptVo();
        beanCopier.copy(entity, vo, null);
        return vo;
    }

    /**
     * 通过登录账号查询用户
     *
     * @param loginName 登录账号
     * @return 用户对象信息
     */
    public SysUserVo selectUserByLoginName(String loginName) {
        //SysUser sysUser = userRepository.findByLoginName(loginName);
        List<SysUser> userList = userRepository.findByLoginNameAndIsDeleted(loginName, 0);
        if (userList.isEmpty()){
            return null;
        }
        SysUser sysUser = userList.get(0);

        BeanCopier beanCopier = BeanCopier.create(SysUser.class, SysUserVo.class, false);
        SysUserVo vo = new SysUserVo();
        beanCopier.copy(sysUser, vo, null);

        // 查询部门信息
        Optional<SysDept> optional = deptRepository.findById(vo.getDeptId());
        if (optional.isPresent()) {
            SysDept sysDept = optional.get();
            BeanCopier deptCopier = BeanCopier.create(SysDept.class, SysDeptVo.class, false);
            SysDeptVo deptVo = new SysDeptVo();
            deptCopier.copy(sysDept, deptVo, null);
            vo.setDept(deptVo);
        }

        return vo;
    }

    /**
     * 通过用户ID查询用户
     *
     * @param userId 用户ID
     * @return 用户对象信息
     */
    public SysUserVo selectUserById(Long userId) {
        Optional<SysUser> optional = userRepository.findById(userId);
        if (!optional.isPresent()) {
            throw new CustomException("用户不存在");
        }
        SysUser sysUser = optional.get();

        BeanCopier beanCopier = BeanCopier.create(SysUser.class, SysUserVo.class, false);
        SysUserVo vo = new SysUserVo();
        beanCopier.copy(sysUser, vo, null);

        Optional<SysDept> deptOptional = deptRepository.findById(vo.getDeptId());
        if (!deptOptional.isPresent()) {
            throw new CustomException("部门不存在");
        }
        SysDept sysDept = deptOptional.get();
        BeanCopier deptBeanCopier = BeanCopier.create(SysDept.class, SysDeptVo.class, false);
        SysDeptVo deptVo = new SysDeptVo();
        deptBeanCopier.copy(sysDept, deptVo, null);
        vo.setDept(deptVo);

        return vo;
    }

    /**
     * 查询用户所属角色名称组
     *
     * @param userId 用户ID
     * @return 结果
     */
    public String selectUserRoleGroup(Long userId) {
        StringBuffer idsStr = new StringBuffer();

        Optional<SysUser> optional = userRepository.findById(userId);
        if (!optional.isPresent()) {
            return idsStr.toString();
        }

        List<Long> roleIds = userRoleRepository.findByUserId(userId).stream().map(SysUserRole::getRoleId).collect(Collectors.toList());
        if (roleIds.isEmpty()) {
            return idsStr.toString();
        }

        List<SysRole> list = roleRepository.findByIdIn(roleIds);
        for (SysRole role : list) {
            idsStr.append(role.getRoleName()).append(",");
        }
        if (StringUtils.isNotEmpty(idsStr.toString())) {
            return idsStr.substring(0, idsStr.length() - 1);
        }

        return idsStr.toString();
    }

    /**
     * 校验登录账号是否唯一
     *
     * @param loginName 登录账号
     * @return 结果
     */
    public String checkLoginNameUnique(String loginName) {
        int count = userRepository.countByLoginNameAndIsDeleted(loginName, DelFlagEnum.OK.value());
        if (count > 0) {
            return Constants.NOT_UNIQUE;
        }
        return Constants.UNIQUE;
    }

    /**
     * 校验手机号码是否唯一
     *
     * @param user 用户信息
     * @return
     */
    public String checkPhoneUnique(SysUserVo user) {
        Long userId = StringUtils.isNull(user.getId()) ? -1L : user.getId();
        SysUser info = userRepository.findByPhoneAndIsDeleted(user.getPhone(), DelFlagEnum.OK.value());
        if (StringUtils.isNotNull(info) && info.getId().longValue() != userId.longValue()) {
            return Constants.NOT_UNIQUE;
        }
        return Constants.UNIQUE;
    }

    /**
     * 校验email是否唯一
     *
     * @param user 用户信息
     * @return
     */
    public String checkEmailUnique(SysUserVo user) {
        Long userId = StringUtils.isNull(user.getId()) ? -1L : user.getId();
        SysUser info = userRepository.findByEmailAndIsDeleted(user.getEmail(), DelFlagEnum.OK.value());
        if (StringUtils.isNotNull(info) && info.getId().longValue() != userId.longValue()) {
            return Constants.NOT_UNIQUE;
        }
        return Constants.UNIQUE;
    }

    /**
     * 校验用户是否允许操作
     *
     * @param user 用户信息
     */
    public void checkUserAllowed(SysUserVo user) {
        if (StringUtils.isNotNull(user.getId()) && SecurityUtils.isAdmin(user.getId())) {
            throw new CustomException("不允许操作超级管理员用户");
        }
    }

    /**
     * 新增用户信息
     *
     * @param vo 用户信息
     * @return 结果
     */
    @Transactional
    public void saveUser(SysUserVo vo) {
        Optional<SysDept> optional = deptRepository.findById(vo.getDeptId());
        if (!optional.isPresent()) {
            throw new CustomException("部门不存在");
        }
        Integer status = optional.get().getStatus();
        if (status == null || status == StatusEnum.DISABLE.value()) {
            throw new CustomException("部门已停用");
        }

        BeanCopier beanCopier = BeanCopier.create(SysUserVo.class, SysUser.class, false);
        SysUser entity = new SysUser();
        beanCopier.copy(vo, entity, null);

        LoginUser loginUser = SecurityUtils.getLoginUser();
        SysUserVo user = loginUser.getUser();

        entity.setIsDeleted(DelFlagEnum.OK.value());
        entity.setCreateUserId(user.getId());
        entity.setCreateTime(new Date());

        // 新增用户信息
        entity = userRepository.save(entity);
        vo.setId(entity.getId());

        // 新增用户与角色管理
        this.insertUserRole(vo);
    }

    /**
     * 修改用户信息
     *
     * @param vo 用户信息
     * @return 结果
     */
    @Transactional(rollbackFor = Exception.class)
    public void updateUser(SysUserVo vo) {
        Optional<SysDept> deptOptional = deptRepository.findById(vo.getDeptId());
        if (!deptOptional.isPresent()) {
            throw new CustomException("部门不存在");
        }
        Integer status = deptOptional.get().getStatus();
        if (status == null || status == StatusEnum.DISABLE.value()) {
            throw new CustomException("部门已停用");
        }

        Long userId = vo.getId();
        Optional<SysUser> optional = userRepository.findById(userId);
        if (!optional.isPresent()) {
            throw new CustomException("用户不存在");
        }
        SysUser entity = optional.get();

        LoginUser loginUser = SecurityUtils.getLoginUser();
        SysUserVo user = loginUser.getUser();

        // 删除用户与角色关联
        userRoleRepository.deleteByUserId(userId);

        // 新增用户与角色管理
        insertUserRole(vo);

        // 修改用户信息
        entity.setUserName(vo.getUserName());
        entity.setDeptId(vo.getDeptId());
        entity.setPhone(vo.getPhone());
        entity.setEmail(vo.getEmail());
        entity.setGender(vo.getGender());
        entity.setStatus(vo.getStatus());
        entity.setUpdateUserId(user.getId());
        entity.setUpdateTime(new Date());
        userRepository.save(entity);
    }

    /**
     * 修改用户状态
     *
     * @param vo 用户信息
     * @return 结果
     */
    public void updateUserStatus(SysUserVo vo) {
        Optional<SysUser> optional = userRepository.findById(vo.getId());
        if (!optional.isPresent()) {
            throw new CustomException("用户不存在");
        }
        SysUser entity = optional.get();

        LoginUser loginUser = SecurityUtils.getLoginUser();
        SysUserVo user = loginUser.getUser();

        entity.setUpdateUserId(user.getId());
        entity.setUpdateTime(new Date());
        entity.setStatus(vo.getStatus());
        userRepository.save(entity);
    }

    /**
     * 修改用户基本信息
     *
     * @param vo 用户信息
     * @return 结果
     */
    public void updateUserProfile(SysUserVo vo) {
        Optional<SysUser> optional = userRepository.findById(vo.getId());
        if (!optional.isPresent()) {
            throw new CustomException("用户不存在");
        }
        SysUser entity = optional.get();

        LoginUser loginUser = SecurityUtils.getLoginUser();
        SysUserVo user = loginUser.getUser();

        entity.setUserName(vo.getUserName());
        entity.setPhone(vo.getPhone());
        entity.setEmail(vo.getEmail());
        entity.setGender(vo.getGender());
        entity.setUpdateUserId(user.getId());
        entity.setUpdateTime(new Date());
        userRepository.save(entity);
    }

    /**
     * 修改用户头像
     *
     * @param userId 用户ID
     * @param avatar 头像
     */
    public void updateUserAvatar(Long userId, String avatar) {
        Optional<SysUser> optional = userRepository.findById(userId);
        if (!optional.isPresent()) {
            throw new CustomException("用户不存在");
        }
        SysUser entity = optional.get();

        LoginUser loginUser = SecurityUtils.getLoginUser();
        SysUserVo user = loginUser.getUser();

        entity.setAvatar(avatar);
        entity.setUpdateUserId(user.getId());
        entity.setUpdateTime(new Date());
        userRepository.save(entity);
    }

    /**
     * 重置用户密码
     *
     * @param vo 用户信息
     * @return 结果
     */
    public void resetPwd(SysUserVo vo) {
        Optional<SysUser> optional = userRepository.findById(vo.getId());
        if (!optional.isPresent()) {
            throw new CustomException("用户不存在");
        }
        SysUser entity = optional.get();

        LoginUser loginUser = SecurityUtils.getLoginUser();
        SysUserVo user = loginUser.getUser();

        entity.setPassword(SecurityUtils.encryptPassword(vo.getPassword()));
        entity.setUpdateUserId(user.getId());
        entity.setUpdateTime(new Date());
        userRepository.save(entity);
    }

    /**
     * 重置用户密码
     *
     * @param loginName 登录账号
     * @param password  密码
     * @return 结果
     */
    public void resetUserPwd(String loginName,String password, String newPassword) {
        SysUser entity = userRepository.findByLoginNameAndPassword(loginName,password);
        if (entity == null) {
            throw new CustomException("用户不存在");
        }

        entity.setPassword(newPassword);
        userRepository.save(entity);
    }

    /**
     * 新增用户角色信息
     *
     * @param vo 用户对象
     */
    public void insertUserRole(SysUserVo vo) {
        List<Long> roleIds = vo.getRoleIds();
        if (StringUtils.isNull(roleIds)) {
            return;
        }

        // 新增用户与角色管理
        List<SysUserRole> list = roleIds.stream().map(roleId -> {
            SysUserRole ur = new SysUserRole();
            ur.setUserId(vo.getId());
            ur.setRoleId(roleId);
            return ur;
        }).collect(Collectors.toList());
        userRoleRepository.saveAll(list);
    }

    /**
     * 通过用户ID删除用户
     *
     * @param userId 用户ID
     * @return 结果
     */
    public void deleteUserById(Long userId) {
        // 删除用户与角色关联
        userRoleRepository.deleteByUserId(userId);

        // 删除用户
        userRepository.deleteById(userId);
    }

    /**
     * 批量删除用户信息
     *
     * @param userIds 需要删除的用户ID
     * @return 结果
     */
    public void deleteUserByIds(List<Long> userIds) {
        for (Long userId : userIds) {
            checkUserAllowed(new SysUserVo(userId));
        }

        List<SysUser> list = userRepository.findByIdIn(userIds);

        list.forEach(user -> {
            user.setIsDeleted(DelFlagEnum.DELETED.value());
        });

        userRepository.saveAll(list);
    }

}
